home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 07 - 1991 / 07.08 Aug 91 / ListHandler Code / TrueLDEF.c < prev   
Encoding:
C/C++ Source or Header  |  1990-06-29  |  8.1 KB  |  303 lines  |  [TEXT/KAHL]

  1. /*                                        LDEF Resource.c                                            */
  2. /*
  3.  * Copyright © 1989, 1990 Martin Minow and MacTutor.
  4.  *
  5.  * You may use this software in any application and
  6.  * redistribute this source without restriction as long
  7.  * as this copyright and permission notice remains intact
  8.  * and the source is not redistributed for profit and you
  9.  * assume all responsibility for the proper operation of
  10.  * this software.
  11.  *
  12.  * Written in Think C.  Set Tabs every 2 characters.
  13.  */
  14. #define FORMAT    TRUE_RESOURCE
  15. #ifdef DOCUMENTATION
  16.  
  17. Usage
  18.  
  19.         void                                                        /* COMPILED only            */
  20.         add_LDEF(list)                                    /* ...                                */
  21.         ListHandle            list;                        /* ...                                */
  22.         
  23.         void                                                        /* COMPILED only            */
  24.         remove_LDEF(list)                                /* ...                                */
  25.         ListHandle            list;                        /* ...                                */
  26.         
  27.         void                                                        /* FAKE_RESOURCE only    */
  28.         setup_LDEF(id)                                    /* ...                                */
  29.         int                            id;                            /* ...                                */
  30.                 
  31. User-provided function:
  32.  
  33.         void
  34.         my_draw_function(
  35.             Rect    *lRrect,                /* Drawing rectangle                    */
  36.             Cell  lCcell,                    /* Cell to redraw                            */
  37.             short lDataOffset,        /* Offset to cell to redraw        */
  38.             short lDataLen,                /* Length of cell's data            */
  39.             ListHandle lHandle        /* The list handle                        */
  40.         )
  41.  
  42.         Note: this is called using C calling conventions --
  43.         mostly because I couldn't convince Think C to compile
  44.         it as a pascal function.
  45.         
  46. Description
  47.  
  48.         Initialize your list as follows:
  49.         
  50.         setup_LDEF(resource_id);    /* FAKE_RESOURCE only                */
  51.         resource_id = 0;                    /* COMPILED only                        */
  52.         resource_id = <id>;                /* FAKE_ or TRUE_RESOURCE        */
  53.         TextFont( ... );                    /* Font of your choice            */
  54.         TextSize( ... );                    /* Whatever you choose            */
  55.         myList = LNew(
  56.             &box,                                        /* Display dimensions                */
  57.             &dimension,                            /* Shape (rows, cols)                */
  58.             cell,                                        /* Cell shape on screen            */
  59.             resource_id,                        /* List func, if any                */
  60.             dialog,                                    /* The window                                */
  61.             FALSE,                                    /* Don't draw yet                        */
  62.             FALSE,                                    /* No grow box                            */
  63.             FALSE,                                    /* no horizontal scroll            */
  64.             TRUE                                        /* Vertical scroll                    */
  65.         );
  66.         add_LDEF(myList);                    /* COMPILED only                        */
  67.         (**myList).refCon = my_draw_function;
  68.  
  69.         Now, whenever the list manager needs to draw something,
  70.         the LDEF handler function will be called.  If the list
  71.         refCon is zero, the LDEF handler operates identically
  72.         to the standard, except that it preserves font and font
  73.         size information.  This is all you need if you wish to
  74.         draw a text list in a dialog using other than the system
  75.         font.
  76.         
  77.         If the refCon is set to a user function, the function
  78.         will be called after the following initialization has
  79.         been completed:
  80.         
  81.         • The pen is "normal" and positioned properly to draw
  82.           the text.
  83.         • The cell to be drawn is locked.
  84.         • The drawing rectangle is erased.
  85.         • The font and font size are set to values in the list's
  86.           port.
  87.          
  88.         The simplest user function need only draw the cell:
  89.         
  90.             DrawText(*((**lHandle).cells), lDataOffset, lDataLen);
  91.             
  92.         A more complicated user function may get the cell's
  93.         contents (using LGetCell) and perform some function
  94.         based on that information.
  95.         
  96.         If you have compiled the LDEF function, be sure to call
  97.         remove_LDEF() before exiting: otherwise, your program
  98.         will crash:
  99.         
  100.         remove_LDEF(myList);            /* COMPILED only                        */
  101.         LDispose(myList);
  102.         
  103. Author
  104.  
  105.         Martin Minow
  106.         
  107.         Thanks to Amanda Walker, InterCon Corporation,
  108.         for the call-back idea.
  109.  
  110. #endif
  111.  
  112. /*
  113.  * These values configure the demo program: that way
  114.  * we only need to write one piece of code.
  115.  */
  116. #define COMPILED            0
  117. #define    FAKE_RESOURCE    1
  118. #define    TRUE_RESOURCE    2
  119. #include <Color.h>
  120. #define NIL        0
  121. typedef short    word;
  122. /*
  123.  * The current ListHandle is always in local variable list.
  124.  */
  125. #define LIST        (**list)
  126.  
  127. /*
  128.  * This structure defines the fake LDEF resource.
  129.  */
  130. typedef struct {
  131.     word    instruction;
  132.     void    (*function)();
  133. } LDEF_record, *LDEF_pointer, **LDEF_handle;
  134.  
  135. /*
  136.  * Externally visible functions.
  137.  */
  138. #if FORMAT == FAKE_RESOURCE
  139. void                setup_LDEF(int);
  140. #endif
  141. #if FORMAT == COMPILED
  142. void                add_LDEF(ListHandle);
  143. void                remove_LDEF(ListHandle);
  144. #endif
  145. #if FORMAT == TRUE_RESOURCE
  146. pascal void    main(
  147.                 int, Boolean, Rect *, Cell, int, int, ListHandle);
  148. #else
  149. static pascal void    myListDef(
  150.                 int, Boolean, Rect *, Cell, int, int, ListHandle);
  151. #endif
  152.  
  153. /*
  154.  * Define the type of the callback function. Amanda Walker
  155.  * calls this "the cast from hell", and with good reason.
  156.  */
  157. typedef    void (* FUNC)(Rect *, Cell, word, word, ListHandle);
  158.  
  159. #if FORMAT == COMPILED
  160. /*
  161.  * Call this after calling LNew for any list that is to
  162.  * use this list definition routine.  It creates a handle
  163.  * and fills it with enough code to jump to myListDef.
  164.  * Note that we do not use a LDEF resource.
  165.  */
  166. void
  167. add_LDEF(list)
  168. ListHandle        list;
  169. {
  170.         LDEF_handle        ldef;
  171.         
  172.         ldef = (LDEF_handle) NewHandle(sizeof (LDEF_record));
  173.         if (ldef != NIL) {
  174.             (**ldef).instruction = 0x4EF9;    /* JMP instruction    */
  175.             (**ldef).function = myListDef;
  176.             LIST.listDefProc = (Handle) ldef;
  177.         }
  178. }
  179.  
  180. /*
  181.  * Be sure to call this before deleting the list.
  182.  * Otherwise, you'll have random program crashes.
  183.  */
  184. void
  185. remove_LDEF(list)
  186. ListHandle        list;
  187. {
  188.         LIST.listDefProc = NIL;
  189. }
  190. #endif
  191.  
  192. #if FORMAT == FAKE_RESOURCE
  193. /*
  194.  * Call this once when your application starts if it uses
  195.  * the list definition function.  You only need to call it
  196.  * once, even if several lists use this function.
  197.  */
  198. void
  199. setup_LDEF(id)
  200. int            id;
  201. {
  202.         LDEF_handle        ldef;
  203.     
  204.         ldef = (LDEF_handle) Get1Resource('LDEF', id);
  205.         if (ldef != NIL
  206.          && GetHandleSize(ldef) == sizeof (LDEF_record)) {
  207.             (**ldef).instruction = 0x4EF9;
  208.             (**ldef).function = myListDef;
  209.             HNoPurge(ldef);
  210.         }
  211. }
  212. #endif
  213.  
  214. /*
  215.  * myListDef() is called by the Macintosh list manager.  It
  216.  * is identical to the standard function, except that it
  217.  * preserves font and size and may call a user function
  218.  * for strange data formatting.
  219.  */
  220. #if FORMAT == TRUE_RESOURCE
  221. pascal void main
  222. #else
  223. static pascal void myListDef
  224. #endif
  225.         (message, select, rect, cell, offset, length, list)
  226. int                    message;    /* List manager action                        */
  227. Boolean            select;        /* TRUE if cell is to be selected    */
  228. Rect                *rect;        /* Rectangle to draw cell in            */
  229. Cell                cell;            /* The selected cell                            */
  230. int                    offset;        /* Start of data in the list            */
  231. int                    length;        /* Number of bytes to draw                */
  232. ListHandle    list;            /* The list itself.                                */
  233. {
  234.         int                    old_font;
  235.         int                    old_size;
  236.         FontInfo        info;
  237.         Point                where;
  238.         int                    lock_state;
  239.         long                saved_A5;
  240.         GrafPtr            old_port;
  241.         
  242.         /*
  243.          * This is needed so the drawing code can find the
  244.          * application globals.
  245.          */
  246.         saved_A5 = SetCurrentA5();
  247.         /*
  248.          * If we're compiled, we don't have valid QuickDraw
  249.          * globals (such as thePort), so we use the current
  250.          * port information from the ListRecord.
  251.          */
  252.         GetPort(&old_port);
  253.         SetPort(LIST.port);
  254.         old_font = LIST.port->txFont;            /* Save the old            */
  255.         old_size = LIST.port->txSize;            /* font and size        */
  256.         /*
  257.          * Editorial note: '--' is the C decrement operator,
  258.          * not the typeographer's "long dash".
  259.          */
  260.         if (message-- == 0) {                            /* lInitMsg                    */
  261.             /*
  262.              * Initialization: save indentation.  Note: do not
  263.              * touch select, rect, cell, offset, or length.
  264.              */
  265.             GetFontInfo(&info);
  266.           LIST.indent.v = info.ascent;
  267.           LIST.indent.h = 4;                        /* Arbitrary                    */
  268.         }
  269.         else if (message-- == 0) {            /* lDrawMsg                        */
  270.             where = topLeft(*rect);
  271.             AddPt(LIST.indent, &where);
  272.             MoveTo(where.h, where.v);
  273.             PenNormal();
  274.             lock_state = HGetState(LIST.cells);
  275.             HLock(LIST.cells);
  276.             EraseRect(rect);
  277.             TextFont((LIST.port)->txFont);
  278.             TextSize((LIST.port)->txSize);
  279.             /*
  280.              * We're ready to roll.  If there's a user-provided
  281.              * function, call it.  Otherwise, just draw text.
  282.              */
  283.             if (LIST.refCon == NIL)
  284.                 DrawText(*(LIST.cells), offset, length);
  285.             else {
  286.                 (*(FUNC) (LIST.refCon))
  287.                                         (rect, cell, offset, length, list);
  288.             }        
  289.             HSetState(LIST.cells, lock_state);
  290.             if (select)                                            /* If selected            */
  291.                 goto hilite;                                    /* go hilite it            */
  292.         }
  293.         else if (message-- == 0) {                /* lHiliteMsg                */
  294. hilite:
  295.             HiliteMode &= ~(1 << hiliteBit);    /* IM V-62                */
  296.           InvertRect(rect);
  297.         }
  298.         TextFont(old_font);
  299.         TextSize(old_size);
  300.         SetA5(saved_A5);
  301. }
  302.  
  303.